package org.jeecg.modules.order.service.impl;

import cn.hutool.core.date.DateUnit;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.coupon.entity.MyCoupon;
import org.jeecg.modules.coupon.mapper.MyCouponMapper;
import org.jeecg.modules.order.entity.Order;
import org.jeecg.modules.order.mapper.OrderMapper;
import org.jeecg.modules.order.service.IOrderService;
import org.jeecg.modules.recharge.entity.Balance;
import org.jeecg.modules.recharge.entity.OrderRecharge;
import org.jeecg.modules.recharge.mapper.BalanceMapper;
import org.jeecg.modules.recharge.mapper.OrderRechargeMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.util.DateUtil;
import org.jeecg.modules.system.util.MenJinUtil;
import org.jeecg.modules.voucher.entity.Voucher;
import org.jeecg.modules.voucher.mapper.VoucherMapper;
import org.jeecg.modules.zixishi.entity.Quyu;
import org.jeecg.modules.zixishi.entity.Seat;
import org.jeecg.modules.zixishi.entity.Zixishi;
import org.jeecg.modules.zixishi.mapper.QuyuMapper;
import org.jeecg.modules.zixishi.mapper.SeatMapper;
import org.jeecg.modules.zixishi.mapper.ZixishiMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Description: 订单
 * @Author: jeecg-boot
 * @Date:   2024-05-19
 * @Version: V1.0
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private MyCouponMapper myCouponMapper;
    @Autowired
    private SeatMapper seatMapper;
    @Autowired
    private QuyuMapper quyuMapper;
    @Autowired
    private ZixishiMapper zixishiMapper;
    @Autowired
    private VoucherMapper voucherMapper;
    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private BalanceMapper balanceMapper;
    @Autowired
    private OrderRechargeMapper orderRechargeMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public int backMoney(Order order) {
        Order o = this.baseMapper.selectById(order.getId());
        Date start = o.getStartTime();
        Date end = o.getEndTime();
        String status = o.getOrderStatus();
        if(StringUtils.contains("123",status)){
            o.setOrderStatus("5");
            return this.baseMapper.updateById(o);
        }else{
            return -1;
        }
    }

    @Override
    public void doOrder(LoginUser sysUser, Order order, Voucher voucher) {
        String reserveType = order.getReserveType();
        if(reserveType.equals("datetime")){
            reserveType = "小时预约";
        }else{
            reserveType = "按天预约";
        }
        order.setSysUserId(sysUser.getId());

        order.setOrderName(reserveType + "订单");
        order.setOrderNum("" + FillRuleUtil.executeRule("shop_order_num", new JSONObject()));
        if(Double.parseDouble(order.getOrderMoney())>0){
            order.setOrderStatus("0");
            redisUtil.set("orderseat:quxiao:" + order.getOrderNum(), "", 5*60);
        }else{
            order.setOrderStatus("1");
            order.setPayType("3");
            order.setPayTime(new Date());
            order.setQrcode(MenJinUtil.genQrCode(order,seatMapper.selectById(order.getSeatId()),quyuMapper.selectById(order.getQuyuId()),zixishiMapper.selectById(order.getZixishiId())));
            int minutes = DateUtil.minuteDiff(new Date(),order.getStartTime());
            minutes = minutes>0?minutes:1;
            redisUtil.set("orderseat:start:" + order.getOrderNum(), "",60*minutes);
        }
        this.baseMapper.insert(order);
        if(null!=voucher){
            voucher.setUseStatus(1);
            voucherMapper.updateById(voucher);
            redisUtil.del("voucher:end:" + voucher.getId());
        }
    }

    @Override
    public Order doOrder4Coupon(LoginUser sysUser,Order order, MyCoupon myCoupon) {
        String reserveType = order.getReserveType();
        if(reserveType.equals("datetime")){
            reserveType = "小时预约";
        }else{
            reserveType = "按天预约";
        }

        order.setSysUserId(sysUser.getId());
        order.setOrderStatus("1");
        order.setOrderName(reserveType + "订单");
        order.setOrderNum("" + FillRuleUtil.executeRule("shop_order_num", new JSONObject()));
        order.setPayType("2");
        order.setOrderMoney(myCoupon.getDisAmt().toPlainString());
        order.setPayTime(new Date());

        Seat seat = seatMapper.selectById(order.getSeatId());
        Quyu quyu = quyuMapper.selectById(order.getQuyuId());
        Zixishi zixishi = zixishiMapper.selectById(order.getZixishiId());
        String url = MenJinUtil.genQrCode(order,seat,quyu,zixishi);
        order.setQrcode(url);
        this.baseMapper.insert(order);
        myCoupon.setUseStatus(1);
        myCoupon.setUseTime(new Date());
        myCouponMapper.updateById(myCoupon);

        int minutes = DateUtil.minuteDiff(new Date(),order.getStartTime());
        minutes = minutes>0?minutes:1;
        redisUtil.set("orderseat:start:" + order.getOrderNum(), "",60*minutes);
//        redisUtil.del("mycoupon:end:" + myCoupon.getId());
        return order;
    }

    @Override
    public void back4WxPay(Order order,Float backMoney) {
        Float money = Float.valueOf(order.getOrderMoney());
        Result<Integer> res = new Result<Integer>();
        WxPayRefundV3Request request = new WxPayRefundV3Request();
        WxPayRefundV3Request.Amount am = new WxPayRefundV3Request.Amount();
        am.setTotal(((Float) (money * 100)).intValue());//原订单金额
        am.setCurrency("CNY");
        am.setRefund(((Float) (backMoney * 100)).intValue());
        //金额信息
        request.setAmount(am);
        //transaction_id:微信支付订单号
        request.setOutTradeNo(order.getOrderNum());
        request.setTransactionId(order.getWxOrderId());
        //商户订单号
        request.setOutRefundNo("seatorder_return_" + order.getOrderNum());
        request.setNotifyUrl(wxPayService.getConfig().getPayScoreNotifyUrl());
        try {
            //调用微信V3退款API
            WxPayRefundV3Result result = wxPayService.refundV3(request);
            String status = result.getStatus();
            order.setBackStatus("0");
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
        this.baseMapper.updateById(order);
    }

    @Override
    public void back4Balance(Order order, Float backMoney) {
        Balance balance = balanceMapper.selectOne(new LambdaQueryWrapper<Balance>().eq(Balance::getSysUserId,order.getSysUserId()));
        if(balance==null){
            balance = new Balance();
            balance.setSysUserId(order.getSysUserId());
            balance.setBalance(new BigDecimal(0));
        }
        balance.setBalance(balance.getBalance().add(new BigDecimal(backMoney)));
        if(StringUtils.isNotBlank(balance.getId())){
            balanceMapper.updateById(balance);
        }else{
            balanceMapper.insert(balance);
        }
        OrderRecharge recharge = new OrderRecharge();
        recharge.setOrderName("订单退款-" + order.getOrderNum());
        recharge.setAmountTotal(String.valueOf(backMoney));
        recharge.setRechargeTotal(String.valueOf(backMoney));
        recharge.setSysUserId(order.getSysUserId());
        recharge.setPayStatus("1");
        orderRechargeMapper.insert(recharge);
        this.baseMapper.updateById(order);
    }

    @Override
    public void back4Coupon(Order order, Float backMoney,int leftHours,int leftDays) {
        String myCouponId = order.getMyCouponId();
        if(StringUtils.isNotBlank(myCouponId)){
            MyCoupon myCoupon = myCouponMapper.selectById(myCouponId);
            if(myCoupon!=null){
                if(StringUtils.equals("datetime",order.getReserveType())){
                    long t = cn.hutool.core.date.DateUtil.between(order.getStartTime(),order.getEndTime(), DateUnit.MINUTE);
                    float tt = t%30>0?(t/60f)+0.5f:t/60f;
                    if(leftHours<1){
                        tt = tt-1;
                    }
                    tt = tt<0?0:tt;
                    myCoupon.setDurationLeft(myCoupon.getDurationLeft()+tt);
                }else{
                    long d = cn.hutool.core.date.DateUtil.between(order.getStartTime(),order.getEndTime(), DateUnit.DAY)+1;
                    if(leftDays<1){
                        d = d-1;
                    }
                    d = d<0?0:d;
                    myCoupon.setDurationLeft(myCoupon.getDurationLeft()+d);
                }
                myCouponMapper.updateById(myCoupon);
                this.baseMapper.updateById(order);
//                long days = cn.hutool.core.date.DateUtil.betweenDay(new Date(), myCoupon.getEndDate(), true);
//                redisUtil.set("mycoupon:end:" + myCoupon.getId(), "", 60 * 60 * 24 * days);
            }
        }
    }

    @Override
    public List<Map> topnUser() {
        return this.baseMapper.topnUser();
    }

    @Override
    public List<Map> topnSeat() {
        return this.baseMapper.topnSeat();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> payOrder(String userId, String orderNum) throws Exception{
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getSysUserId,userId).eq(Order::getOrderNum, orderNum));
        if(null == order){
            throw new Exception("订单不存在，请确认");
        }

        Balance balance = balanceMapper.selectOne(new LambdaQueryWrapper<Balance>().eq(Balance::getSysUserId, userId));
        if(null == balance){
            throw new Exception("余额不足，请确认");
        }
        Float orderMoney = Float.valueOf(order.getOrderMoney());
        Float money = balance.getBalance().floatValue();
        if(money < orderMoney){
            throw new Exception("余额不足，请确认");
        }
        balance.setBalance(new BigDecimal(money-orderMoney));
        balanceMapper.updateById(balance);
        order.setPayType("1");
        order.setPayTime(new Date());
        order.setOrderStatus("1");
        Seat seat = seatMapper.selectById(order.getSeatId());
        Quyu quyu = quyuMapper.selectById(order.getQuyuId());
        Zixishi zixishi = zixishiMapper.selectById(order.getZixishiId());
        String url = MenJinUtil.genQrCode(order,seat,quyu,zixishi);
        order.setQrcode(url);
        orderMapper.updateById(order);
        int minutes = DateUtil.minuteDiff(new Date(),order.getStartTime());
        minutes = minutes>0?minutes:1;
        redisUtil.set("orderseat:start:" + order.getOrderNum(), "",60*minutes);
        redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
        return Result.ok("支付成功");
    }

    @Override
    public Result<String> addOrder(LoginUser sysUser,Order order) throws Exception{
        order.setOrderNum("" + FillRuleUtil.executeRule("shop_order_num", new JSONObject()));
        orderMapper.insert(order);
        if(!StringUtils.equals("0",order.getOrderStatus())){
            Seat seat = seatMapper.selectById(order.getSeatId());
            Quyu quyu = quyuMapper.selectById(order.getQuyuId());
            Zixishi zixishi = zixishiMapper.selectById(order.getZixishiId());
            String url = MenJinUtil.genQrCode(order,seat,quyu,zixishi);
            order.setQrcode(url);
            orderMapper.updateById(order);
        }
        if(StringUtils.equals("1",order.getOrderStatus())){
            int minutes = DateUtil.minuteDiff(new Date(),order.getStartTime());
            minutes= minutes>0?minutes:1;
            redisUtil.set("orderseat:start:" + order.getOrderNum(), "",60*minutes);
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
        }else if(StringUtils.equals("2",order.getOrderStatus())){
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
            redisUtil.del("orderseat:start:" + order.getOrderNum());
            int minutes = DateUtil.minuteDiff(new Date(),order.getEndTime());
            minutes= minutes>0?minutes:1;
            if(minutes>10) {
                redisUtil.set("orderseat:xudan:" + order.getOrderNum(), "", 60 * (minutes - 10));
            }
            redisUtil.set("orderseat:end:" + order.getOrderNum(), "", 60*(minutes));
        }else if(StringUtils.equals("3",order.getOrderStatus())){
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
            redisUtil.del("orderseat:start:" + order.getOrderNum());
            redisUtil.del("orderseat:xudan:" + order.getOrderNum());
            redisUtil.del("orderseat:end:" + order.getOrderNum());
        }
        return Result.ok("操作成功");
    }

    @Override
    public Result<String> editOrder(LoginUser sysUser, Order order) throws Exception {

        if(!StringUtils.equals("0",order.getOrderStatus())){
            Seat seat = seatMapper.selectById(order.getSeatId());
            Quyu quyu = quyuMapper.selectById(order.getQuyuId());
            Zixishi zixishi = zixishiMapper.selectById(order.getZixishiId());
            String url = MenJinUtil.genQrCode(order,seat,quyu,zixishi);
            order.setQrcode(url);
        }
        orderMapper.updateById(order);
        if(StringUtils.equals("1",order.getOrderStatus())){
            int minutes = DateUtil.minuteDiff(new Date(),order.getStartTime());
            minutes= minutes>0?minutes:1;
            redisUtil.set("orderseat:start:" + order.getOrderNum(), "",60*minutes);
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
        }else if(StringUtils.equals("2",order.getOrderStatus())){
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
            redisUtil.del("orderseat:start:" + order.getOrderNum());
            int minutes = DateUtil.minuteDiff(new Date(),order.getEndTime());
            minutes= minutes>0?minutes:1;
            if(minutes>10) {
                redisUtil.set("orderseat:xudan:" + order.getOrderNum(), "", 60 * (minutes - 10));
            }
            redisUtil.set("orderseat:end:" + order.getOrderNum(), "", 60*(minutes));
        }else if(StringUtils.equals("3",order.getOrderStatus())){
            redisUtil.del("orderseat:quxiao:" + order.getOrderNum());
            redisUtil.del("orderseat:start:" + order.getOrderNum());
            redisUtil.del("orderseat:xudan:" + order.getOrderNum());
            redisUtil.del("orderseat:end:" + order.getOrderNum());
        }
        return Result.ok("操作成功");
    }


}
